﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
using UnityEngine.Playables;
using UnityEngine.Timeline;

public class LevelMaking : TimelineBehaviour {

    [SerializeField]
    Camera _camera1;

    [SerializeField]
    Camera _camera2;

    Transform _dragTarget;
    Vector3 _dragTargetStartPos;
    Transform _lastDragTarget;

    [SerializeField]
    Transform _fallingPoint;

    [SerializeField]
    BoxCollider _bowlCollider;

    [SerializeField]
    Transform _jiaoBanQi;

    [SerializeField]
    GameObject _starEffect;

    [SerializeField]
    GameObject _canvas;

    [SerializeField]
    Transform[] _stuffs;

    [SerializeField]
    Transform[] _effects;

    [SerializeField]
    Transform _hand;

    [SerializeField]
    GameObject _ledi;

    Transform _thisTransform;
    Camera _currentCamera;
    bool _showMoveTips = true;
    bool _showClickTips = true;
    bool _canDrag = false;
    Animator _lediAnimator;

    // 0-Egg; 1-Flour; 2-Chocolate; 3-Matcha; 4-Milk; 5-Lemon; 6-Honey; 7-Sugar; 8-Salt; 9-Cherry; 10-Butter
    Stack<int> _stuffsIndexCommon = new Stack<int>(new int[] { 7, 4, 1, 0 });
    Stack<int> _stuffsIndexMiCai = new Stack<int>(new int[] { 7, 4, 3, 2, 1, 0 });
    Stack<int> _stuffsIndexYingHua = new Stack<int>(new int[] { 9, 7, 6, 5, 4, 1, 0 });
    Stack<int> _stuffsIndexPaoFu = new Stack<int>(new int[] { 10, 8, 4, 1, 0 });

    // 0-Egg1; 1-Egg2; 2-Egg3; 3-Flour; 4-Chocolate; 5-Matcha; 6-Milk; 7-Cherry; 8-Butter; 9-Lemon; 10-Honey; 11-Sugar; 12-Salt
    Stack<int> _effectsIndexCommon = new Stack<int>(new int[] { 11, 6, 3, 2, 1, 0 });
    Stack<int> _effectsIndexMiCai = new Stack<int>(new int[] { 11, 6, 5, 4, 3, 2, 1, 0 });
    Stack<int> _effectsIndexYingHua = new Stack<int>(new int[] { 7, 11, 10, 9, 6, 3, 2, 1, 0 });
    Stack<int> _effectsIndexPaoFu = new Stack<int>(new int[] { 8, 12, 6, 3, 2, 1, 0 });


    protected override void Start() {
        base.Start();

        _thisTransform = GetComponent<Transform>();

        if (_camera1 == null) {
            _camera1 = _thisTransform.Find("Camera_1").GetComponent<Camera>();
        }

        if (_camera2 == null) {
            _camera2 = _thisTransform.Find("Camera_2").GetComponent<Camera>();
        }

        if (_fallingPoint == null) {
            _fallingPoint = transform.Find("Bowl").Find("Falling Point");
        }

        _currentCamera = _camera1;
        _lediAnimator = _ledi.GetComponent<Animator>();

        PlayLeDiVoiceAnimation(CakeShopResPath.LeDi_404010201);
    }

    public void Update() {
        if (_canDrag) {
            DragObject();
        }
    }

    void PlayLeDiVoiceAnimation(string voicePath) {
        _lediAnimator.Play("TalkBegin");

        StartCoroutine(TimeUtility.DelayInvoke(0.5f, () => {
            var length = AudioManager.Instance.PlaySound(voicePath).Length;
            StartCoroutine(TimeUtility.DelayInvoke(length, () => _lediAnimator.Play("TalkEnd")));
        }));
    }

    Animator _currentAnimator;
    bool _holdingStuff;
    ParticleSystem[] _particleSystems;

    void DragObject() {
        if (Input.GetMouseButtonDown(0)) {
            if (_dragTarget) {
                _dragTarget.GetComponent<BoxCollider>().enabled = true;
                _dragTarget = null;
            }

            Ray ray = _currentCamera.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit) && !hit.transform.Equals(_fallingPoint.parent) && !hit.transform.parent.Equals(_fallingPoint.parent)) {
                _dragTarget = hit.transform;
                _dragTarget.GetComponent<BoxCollider>().enabled = false;
                EnableBowlCollider(true);

                if (!_dragTarget.name.ToLower().Contains("egg")
                       && !_dragTarget.name.Contains("Cherry")
                       && !_dragTarget.name.Contains("Butter")) {
                    _particleSystems = _dragTarget.Find("Effect").GetComponentsInChildren<ParticleSystem>();
                }

                if (!_dragTarget.name.Contains("Egg")) {
                    _currentAnimator = _dragTarget.GetComponentInChildren<Animator>();

                    if (_currentAnimator) {
                        _currentAnimator.enabled = false;
                        _currentAnimator.Play("Jump", -1, 0f);
                        _currentAnimator.transform.localPosition = Vector3.zero;
                        _currentAnimator.transform.localEulerAngles = Vector3.zero;
                        _currentAnimator.transform.localScale = Vector3.one;
                    }
                } else {
                    _dragTarget.GetComponent<EggController>().EnableJump(false);
                }

                if (_lastDragTarget == null || !_lastDragTarget.Equals(_dragTarget)) {
                    _dragTargetStartPos = _dragTarget.position;
                    _lastDragTarget = _dragTarget;
                }
                
                if (_showMoveTips) {
                    ActiveHand(false);
                    _hand.GetComponent<TRSController>().StayOnStart();
                    _hand.GetComponent<TRSController>().position.loop = true;
                }
            } else {
                _dragTarget = null;
            }
        } else if (Input.GetMouseButton(0)) {
            if (_dragTarget != null) {
                var targetInScreenPos = _currentCamera.WorldToScreenPoint(_fallingPoint.position);
                var mousePos = Input.mousePosition;
                var screenPos = new Vector3(mousePos.x, mousePos.y, targetInScreenPos.z);
                var worldPos = _currentCamera.ScreenToWorldPoint(screenPos);

                // 由于模型中心位于底部中心，故需要进行自身一半高度的位移
                var halfHeight = _dragTarget.GetComponent<BoxCollider>().size.y * 0.5f;
                _dragTarget.position = worldPos - (_dragTarget.up * halfHeight);
                var y = Mathf.Clamp(_dragTarget.position.y, _fallingPoint.position.y - 40f, _dragTarget.position.y);
                _dragTarget.position = new Vector3(_dragTarget.position.x, y, _fallingPoint.position.z);

                // =====================================================================
                if (!_dragTarget.name.ToLower().Contains("egg")
                       && !_dragTarget.name.Contains("Cherry")
                       && !_dragTarget.name.Contains("Butter")) {
                    var posY = Mathf.Clamp(worldPos.y, _fallingPoint.position.y - 20f, worldPos.y);
                    _dragTarget.position = new Vector3(worldPos.x, posY, _fallingPoint.position.z);

                    Ray ray = _currentCamera.ScreenPointToRay(mousePos);
                    RaycastHit hit;

                    if (Physics.Raycast(ray, out hit) && hit.transform.Equals(_fallingPoint.parent)) {
                        var zRotation = 0f;
                        var yRotation = 135f;

                        if (_dragTarget.name.Equals("Milk")) {
                            zRotation = 90f;
                        } else if (_dragTarget.name.Equals("Lemon") || _dragTarget.name.Equals("Honey")) {
                            yRotation = 150f;
                        }

                        if (_holdingStuff) {
                            _dragTarget.Find("Effect").SetActive(true);

                            foreach (var ps in _particleSystems) {
                                var em = ps.emission;
                                em.enabled = true;
                            }

                            ShowEffect(true);
                        } else {
                            _dragTarget.DOLocalRotate(new Vector3(0f, yRotation, zRotation), 0.3f).OnComplete(() => {
                                if (_dragTarget) {
                                    _dragTarget.Find("Effect").SetActive(true);
                                }

                                _holdingStuff = true;
                            });
                        }
                    } else {
                        foreach (var ps in _particleSystems) {
                            var em = ps.emission;
                            em.enabled = false;
                        }

                        ShowEffect(false);
                    }
                }
            }
        } else if (Input.GetMouseButtonUp(0)) {
            if (_dragTarget != null) {
                var pos = _fallingPoint.position;

                if (_holdingStuff) {
                    EnableBowlCollider(false);

                    foreach (var ps in _particleSystems) {
                        var em = ps.emission;
                        em.enabled = false;
                    }

                    if (ShowEffect(false) == false) {
                        _dragTarget.DOMove(pos, 0.3f);
                    }
                } else {
                    Ray ray = _currentCamera.ScreenPointToRay(Input.mousePosition);
                    RaycastHit hit;

                    if (Physics.Raycast(ray, out hit) && hit.transform.Equals(_fallingPoint.parent)) {
                        EnableBowlCollider(false);

                        if (_dragTarget.name.ToLower().Contains("egg")) {
                            _dragTarget.GetComponent<BoxCollider>().enabled = true;
                            var height = _dragTarget.GetComponent<BoxCollider>().bounds.size.y;
                            pos += _dragTarget.forward * (height * 0.5f);

                            _dragTarget.GetComponent<EggController>().SwitchToShake();
                            _dragTarget.gameObject.AddComponent<ClickTrigger>();

                            _dragTarget.DOLocalRotate(new Vector3(0f, 0f, -90f), 0.3f).OnComplete(() => {
                                _hand.GetComponent<TRSController>().StayOnEnd();
                                _hand.GetComponent<TRSController>().position.loop = false;
                                _hand.GetComponent<HandController>().SwitchStateTo(HandController.HandState.Click);
                                ActiveHand(_showClickTips && !_showMoveTips);
                            });

                            _canDrag = false;
                            ActiveHand(false);
                            _showMoveTips = false;
                        } else if (_dragTarget.name.Contains("Cherry") || _dragTarget.name.Contains("Butter")) {
                            var target = _dragTarget;
                            _dragTarget.DOLocalRotate(new Vector3(0f, 135f, 0f), 0.3f).OnComplete(() => {
                                target.Find("Effect").SetActive(true);
                                StartCoroutine(TimeUtility.DelayInvoke(1.5f, PlayTimeline));
                            });
                        }

                        _dragTarget.DOMove(pos, 0.3f);
                    } else {
                        var target = _dragTarget;
                        var endPos = _dragTargetStartPos;
                        _dragTarget.DOMove(endPos, 0.3f).OnComplete(() => {
                            AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010201);
                            ActiveHand(_showMoveTips || _showClickTips);

                            if (_currentAnimator) {
                                _currentAnimator.enabled = true;
                                _currentAnimator = null;
                            }

                            
                            if (target.name.Contains("Egg")) {
                                target.GetComponent<EggController>().EnableJump(true);
                            }
                        });
                    }
                }

                if (_dragTarget) {
                    _dragTarget.GetComponent<BoxCollider>().enabled = true;
                    _dragTarget = null;
                }
            }
        }
    }

    void SwitchCamera() {
        _camera2.gameObject.SetActive(true);
        _camera1.gameObject.SetActive(false);
        _currentCamera = _camera2;
        _jiaoBanQi.SetActive(true);
        _jiaoBanQi.parent.GetComponentInChildren<DragRotation>().enabled = true;
        _bowlCollider.enabled = false;
        ActiveCanvas(true);
    }

    public void LeDiAnimation(bool isTimelineDrive) {
        var bindings = playableDirector.playableAsset.outputs;

        foreach (var b in bindings) {
            if (b.streamName.Equals("LeDi")) {
                playableDirector.SetGenericBinding(b.sourceObject, isTimelineDrive ? _ledi : null);
                break;
            }
        }
    }

    public void ActiveCanvas(bool show) {
        _canvas.SetActive(show);
    }

    public void StopTips() {
        _showClickTips = false;
        _showMoveTips = false;
        ActiveHand(false);
    }

    /// <summary>
    /// 返回纹理资源
    /// </summary>
    /// <param name="oneOrZero">只接受整数 0 或者 1</param>
    /// <returns></returns>
    public Texture SwitchTexture(int oneOrZero) {
        switch (CakeShopManager.Instance.CurrentCakeType) {
            case CakeType.ShengDan:
            case CakeType.CaiHong:
            case CakeType.ShuiGuo:
                return CommonUtility.LoadTexture(oneOrZero == 0 ? CakeShopResPath.TEX_COMMON_0 : CakeShopResPath.TEX_COMMON_1);
            case CakeType.MiCai:
                return CommonUtility.LoadTexture(oneOrZero == 0 ? CakeShopResPath.TEX_MICAI_0 : CakeShopResPath.TEX_MICAI_1);
            case CakeType.YingHua:
                return CommonUtility.LoadTexture(oneOrZero == 0 ? CakeShopResPath.TEX_YINGHUA_0 : CakeShopResPath.TEX_YINGHUA_1);
            case CakeType.PaoFu:
                return CommonUtility.LoadTexture(oneOrZero == 0 ? CakeShopResPath.TEX_COMMON_0 : CakeShopResPath.TEX_COMMON_1);
            default:
                return null;
        }
    }

    public void PlayEggAnimation(Transform t) {
        if (t) {
            t.GetComponent<EggController>().OnClicked();
            t.GetComponent<Animator>().enabled = true;
            StartCoroutine(TimeUtility.DelayInvoke(0.5f, () => {
                ActiveEffect();
                t.DOLocalMoveZ(160f, 0.5f);
                t = null;
                EnableDrag();
            }));
        }
    }

    public void ChangeStuff() {
        if (_particleSystems != null && _particleSystems.Length > 0) {
            foreach (var ps in _particleSystems) {
                var em = ps.emission;
                em.enabled = false;
            }
        }

        switch (CakeShopManager.Instance.CurrentCakeType) {
            case CakeType.ShengDan:
            case CakeType.CaiHong:
            case CakeType.ShuiGuo:
                if (_stuffsIndexCommon.Count > 0) {
                    var tCommon = _stuffs[_stuffsIndexCommon.Pop()];
                    tCommon.GetComponent<BoxCollider>().enabled = false;
                    tCommon.DOLocalMoveZ(150f, 1f);
                }

                if (_stuffsIndexCommon.Count > 0) {
                    var tc = _stuffs[_stuffsIndexCommon.Peek()];
                    tc.DOLocalMoveX(0f, 0.5f).OnComplete(() => tc.GetComponentInChildren<Animator>().enabled = true);
                    AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010203);
                } else {
                    StartCoroutine(TimeUtility.DelayInvoke(1.5f, () => SwitchCamera()));
                }
               
                break;
            case CakeType.MiCai:
                if (_stuffsIndexMiCai.Count > 0) {
                    var tMiCai = _stuffs[_stuffsIndexMiCai.Pop()];
                    tMiCai.GetComponent<BoxCollider>().enabled = false;
                    tMiCai.DOLocalMoveZ(150f, 1f);
                }

                if (_stuffsIndexMiCai.Count > 0) {
                    var tm = _stuffs[_stuffsIndexMiCai.Peek()];
                    tm.DOLocalMoveX(0f, 0.5f).OnComplete(() => tm.GetComponentInChildren<Animator>().enabled = true);
                    AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010203);
                } else {
                    StartCoroutine(TimeUtility.DelayInvoke(1.5f, () => SwitchCamera()));
                }

                break;
            case CakeType.YingHua:
                if (_stuffsIndexYingHua.Count > 0) {
                    var tYingHua = _stuffs[_stuffsIndexYingHua.Pop()];
                    tYingHua.GetComponent<BoxCollider>().enabled = false;
                    tYingHua.DOLocalMoveZ(150f, 1f);
                }

                if (_stuffsIndexYingHua.Count > 0) {
                    var ty = _stuffs[_stuffsIndexYingHua.Peek()];
                    ty.DOLocalMoveX(0f, 0.5f).OnComplete(() => ty.GetComponentInChildren<Animator>().enabled = true);
                    AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010203);
                } else {
                    StartCoroutine(TimeUtility.DelayInvoke(1.5f, () => SwitchCamera()));
                }

                break;
            case CakeType.PaoFu:
                if (_stuffsIndexPaoFu.Count > 0) {
                    var tPaoFu = _stuffs[_stuffsIndexPaoFu.Pop()];
                    tPaoFu.GetComponent<BoxCollider>().enabled = false;
                    tPaoFu.DOLocalMoveZ(150f, 1f);
                }

                if (_stuffsIndexPaoFu.Count > 0) {
                    var tp = _stuffs[_stuffsIndexPaoFu.Peek()];
                    tp.DOLocalMoveX(0f, 0.5f).OnComplete(() => tp.GetComponentInChildren<Animator>().enabled = true);
                    AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010203);
                } else {
                    StartCoroutine(TimeUtility.DelayInvoke(1.5f, () => SwitchCamera()));
                }

                break;
        }
    }

    int _currentEffectIndex = -1;
    float _costTime;
    float _totalTime = 3f;
    GameAudioSource _currentEffectAudio;

    public bool ShowEffect(bool enableEffect) {
        if (enableEffect) {
            _costTime += Time.deltaTime;
            var t = _costTime / _totalTime;

            switch (_currentEffectIndex) {
                // Flour
                case 3:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010204);
                    }

                    _effects[_currentEffectIndex].localPosition = Vector3.Lerp(Vector3.forward * -2f, Vector3.forward * 7f, t);
                    break;
                // Milk
                case 6:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010205);
                    }

                    _effects[_currentEffectIndex].localPosition = Vector3.Lerp(Vector3.forward * 2f, Vector3.forward * 6f, t);
                    _effects[_currentEffectIndex].localScale = Vector3.Lerp(Vector3.one * 0.8f, Vector3.one, t);
                    break;
                // Chocolate
                case 4:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010204);
                    }

                    _effects[_currentEffectIndex].localPosition = Vector3.Lerp(new Vector3(-4f, -2f, -1f), new Vector3(-4f, -2f, 8f), t);
                    break;
                // Matcha
                case 5:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010204);
                    }

                    _effects[_currentEffectIndex].localPosition = Vector3.Lerp(new Vector3(0f, 5f, -1f), new Vector3(0f, 5f, 8f), t);
                    break;
                // Lemon
                case 9:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010205);
                    }

                    _effects[_currentEffectIndex].localPosition = Vector3.Lerp(new Vector3(0f, -1f, 7f), new Vector3(0f, -1f, 8.2f), t);
                    break;
                // Honey
                case 10:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010205);
                    }

                    _effects[_currentEffectIndex].localPosition = Vector3.Lerp(new Vector3(0f, 2f, 7f), new Vector3(0f, 2f, 8.2f), t);
                    break;
                // 11 - Sugar; 12 - Salt
                case 11:
                case 12:
                    if (_currentEffectAudio == null || !_currentEffectAudio.IsPlaying) {
                        _currentEffectAudio = AudioManager.Instance.PlaySound(CakeShopResPath.SE_604010204);
                    }

                    break;
            }
        } else {
            if (_currentEffectAudio != null) {
                _currentEffectAudio.Stop();
                _currentEffectAudio = null;
            }
        }

        if (Input.GetMouseButtonUp(0) && (_costTime / _totalTime) >= 1f) {
            if (_dragTarget) {
                _dragTarget.GetComponent<BoxCollider>().enabled = false;
                _dragTarget = null;
            }

            _holdingStuff = false;
            _currentEffectIndex = -1;
            _costTime = 0f;
            PlayTimeline();
            return true;
        } else {
            return false;
        }
    }

    public void ActiveEffect() {
        switch (CakeShopManager.Instance.CurrentCakeType) {
            case CakeType.ShengDan:
            case CakeType.CaiHong:
            case CakeType.ShuiGuo:
                if (_effectsIndexCommon.Count < 1) {
                    return;
                }
                _currentEffectIndex = _effectsIndexCommon.Pop();
                break;
            case CakeType.MiCai:
                if (_effectsIndexMiCai.Count < 1) {
                    return;
                }
                _currentEffectIndex = _effectsIndexMiCai.Pop();
                break;
            case CakeType.YingHua:
                if (_effectsIndexYingHua.Count < 1) {
                    return;
                }
                _currentEffectIndex = _effectsIndexYingHua.Pop();
                break;
            case CakeType.PaoFu:
                if (_effectsIndexPaoFu.Count < 1) {
                    return;
                }
                _currentEffectIndex = _effectsIndexPaoFu.Pop();
                break;
        }

        _effects[_currentEffectIndex].SetActive(true);
    }

    public void EnableBowlCollider(bool isEnabled) {
        if (_bowlCollider) {
            _bowlCollider.enabled = isEnabled;
        }
    }

    public void ActiveHand(bool isActived) {
        _hand.SetActive(isActived);
    }

    public void EnableDrag() {
        _canDrag = true;
    }

    public void PlayVoice() {
        switch (CakeShopManager.Instance.CurrentCakeType) {
            case CakeType.ShengDan:
            case CakeType.CaiHong:
            case CakeType.ShuiGuo:
                PlayLeDiVoiceAnimation(CakeShopResPath.LeDi_404010202);
                break;
            case CakeType.MiCai:
                PlayLeDiVoiceAnimation(CakeShopResPath.LeDi_404010203);
                break;
            case CakeType.YingHua:
                PlayLeDiVoiceAnimation(CakeShopResPath.LeDi_404010204);
                break;
            case CakeType.PaoFu:
                PlayLeDiVoiceAnimation(CakeShopResPath.LeDi_404010205);
                break;
        }
    }

    public override void PlayTimeline() {
        base.PlayTimeline();
    }

    public override void PauseTimeline(float duration) {
        base.PauseTimeline(duration);
    }

    public void OnEnd() {
        _starEffect.SetActive(true);
        AudioManager.Instance.PlaySound(CakeShopResPath.SE_604020304);       
        StartCoroutine(TimeUtility.DelayInvoke(2f, () => CakeShopManager.Instance.ToNextLevel(CakeShopManager.LevelState.Level_3_Baking)));
    }
}
